/*
 *  Copyright 2008 The MITRE Corporation (http://www.mitre.org/). All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package org.mitre.lattice.lattice;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import org.jgap.Gene;
import org.jgap.impl.IntegerGene;
import org.mitre.mrald.util.Config;
import org.mitre.mrald.util.MraldException;
/**
 *  Sample fitness function for the MakeChange example.
 *
 *@author     jchoyt
 *@created    November 12, 2003
 */
public class LatticeFunctions
{


    private static LatticeFunctionsImpl implmnt = null;
    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     */
    private LatticeFunctions() { }


    public static void setImplmnt()
    {
	   //MraldOutFile.logToFile(Config.getProperty("LOGFILE"), "Lattice Functions setting Implementation : Start " );

	   //MraldOutFile.logToFile(Config.getProperty("LOGFILE"), "Lattice Functions setting Implementation : Config " + Config.getLatticeFactory().toString() );

	    implmnt = Config.getLatticeFactory().getLatticeFunctionImpl() ;
	   //MraldOutFile.logToFile(Config.getProperty("LOGFILE"), "Lattice Functions setting Implementation :  " + implmnt.toString() );

    }

    /**
     *  Description of the Method
     *
     *@param  nowSet  The new isSet value
     */
    public static void setIsSet( boolean nowSet )
    {
        implmnt.setIsSet( nowSet );
    }


    public boolean getIsSet()
    {
	    return implmnt.getIsSet();
    }
    /**
     *  Cycle through the number of nodes and get the maximum possible no of
     *  links if each node is linked to each node in level below. (Not exact but
     *  try for now)
     *
     *@return    The allLinks value
     */
    public static int getAllLinks()
    {
        return implmnt.getAllLinks();
    }


    /**
     *  Cycle through the number of nodes and get the maximum possible no of
     *  links if each node is linked to each node in level below. (Not exact but
     *  try for now)
     *
     *@return    The avgDistance value
     */
    public static int getAvgDistance()
    {
        return implmnt.getAvgDistance();
    }


    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     *
     *@param  screenHeight  Description of the Parameter
     *@return               The boxHeight value
     */
    public static int getBoxHeight( int screenHeight )
    {
        return implmnt.getBoxHeight(screenHeight);
    }


    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     *
     *@return    The boxHeight value
     */
    public static int getBoxHeight()
    {
        return implmnt.getBoxHeight();
    }


    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     *
     *@param  screenWidth  Description of the Parameter
     *@return              The boxWidth value
     */
    public static int getBoxWidth( int screenWidth )
    {
        return implmnt.getBoxWidth( screenWidth);

    }


    /**
     *  Gets the boxWidth attribute of the LatticeFunctions class
     *
     *@return    The boxWidth value
     */
    public static int getBoxWidth()
    {
       return implmnt.getBoxWidth();
    }




    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     *
     *@param  x1  Description of the Parameter
     *@param  x2  Description of the Parameter
     *@param  y1  Description of the Parameter
     *@param  y2  Description of the Parameter
     *@return     The distanceBetweenNodes value
     */
    public static double getDistanceBetweenNodes( double x1, double x2, double y1, double y2 )
    {
        return implmnt.getDistanceBetweenNodes(x1, x2, y1, y2);
    }


    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     *
     *@param  x1  Description of the Parameter
     *@param  x2  Description of the Parameter
     *@param  yd  Description of the Parameter
     *@return     The distanceBetweenNodes value
     */
    public static double getDistanceBetweenNodes( int x1, int x2, int yd )
    {

        return implmnt.getDistanceBetweenNodes(x1, x2, yd);
    }



    /*
     *  Description of the Method
     *
     *  @param  root  Description of the Parameter
     *  @return       Description of the Return Value
     */
    /**
     *  Gets the flatLattice attribute of the LatticeFunctions class
     *
     *@param  root  Description of the Parameter
     *@return       The flatLattice value
     */
    public static ArrayList getFlatLattice( LatticeNode root )
    {
        return implmnt.getFlatLattice(root);
    }


    /**
     *  Gets the flatLattice attribute of the LatticeFunctions class
     *
     *@return    The flatLattice value
     */
    public static ArrayList getFlatLattice()
    {

        return implmnt.getFlatLattice();
    }


    /**
     *  Return the height of the screen
     *
     *@return    The height value
     */
    public static int getHeight()
    {
        return implmnt.getHeight();
    }


    /**
     *@param  node  Description of the Parameter
     *@return       The integer value
     */
    public static Integer getInteger( LatticeNode node )
    {
        return implmnt.getInteger( node );
    }


    /**
     *  Get max values
     *
     *@param  node  Description of the Parameter
     *@return       The levelOfNode value
     */
    public static int getLevelOfNode( LatticeNode node )
    {
        return implmnt.getLevelOfNode(node) ;
    }


    /**
     *  Gets the mapGeneToNode attribute of the LatticeFunctions class
     *
     *@return    The mapGeneToNode value
     */
    public static HashMap getMapGeneToNode()
    {
        return implmnt.getMapGeneToNode();
    }


    /**
     *  Gets the mapNodeToGene attribute of the LatticeFunctions class
     *
     *@return    The mapNodeToGene value
     */
    public static HashMap getMapNodeToGene()
    {
        return implmnt.getMapNodeToGene();
    }


    /**
     *  Get max values
     *
     *@return    The maxLevel value
     */
    public static int getMaxLevel()
    {
        return implmnt.getMaxLevel();
    }


    /**
     *  Get max values
     *
     *@return    The maxNodesPerLevel value
     */
    public static int getMaxNodesPerLevel()
    {
        return implmnt.getMaxNodesPerLevel();
    }


    /**
     *  Gets the nodes that are on the highest level given a starting node.
     *
     *@param  root  Description of the Parameter
     *@return       The nodesOnLevel value
     */
    public static ArrayList getMostDominant( LatticeNode root )
    {
        return implmnt.getMostDominant(root);
    }


    /**
     *  Gets the nodes that are on the highest level given a starting node.
     *
     *@param  levelDown  Description of the Parameter
     *@return            The nodesOnLevel value
     */
    public static ArrayList getMostDominant( int levelDown )
    {
        return implmnt.getMostDominant(levelDown);
    }


    /**
     *  Store the maximum Number of nodes in a level
     *
     *@return    The noOfGrids value
     */
    public static int getNoOfGrids()
    {
        return implmnt.getNoOfGrids();
    }


    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     *
     *@param  nodeInteger  Description of the Parameter
     *@return              The node value
     */
    public static LatticeNode getNode( Integer nodeInteger )
    {
        return implmnt.getNode( nodeInteger );
    }


    /**
     *@param  level  Description of the Parameter
     *@return        The nodesOnLevel value
     */
    public static ArrayList getNodesOnLevel( int level )
    {
        return implmnt.getNodesOnLevel(level);
    }


    /**
     *@param  thisNode  Description of the Parameter
     *@return           The nodesOnSameLevel value
     */
    public static ArrayList getNodesOnSameLevel( LatticeNode thisNode )
    {

        return implmnt.getNodesOnSameLevel(thisNode);
    }


    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     *
     *@param  node  Description of the Parameter
     *@return       The parents value
     */
    public static ArrayList getParents( LatticeNode node )
    {
        return implmnt.getParents(node);
    }


    /**
     *  Takes the x value of the Node, and 'Snaps to Grid' to neaten
     *
     *@return    The rootNode value
     */
    public static LatticeNode getRootNode()
    {
        return implmnt.getRootNode();
    }

    /**
     *  Takes the x value of the Node, and 'Snaps to Grid' to neaten
     *
     *@return    The rootNode value
     */
    public static void setRootNode(LatticeNode rootNode)
    {
        implmnt.setRootNode(rootNode);
    }

    /**
     *  Return the width of the screen
     *
     *@return    The width value
     */
    public static int getWidth()
    {
        return implmnt.getWidth();
    }


    /**
     *  Determine the maximum distance if all the grid positions were filled and
     *  were joined to their neighbours.
     *
     *@param  nodeInteger  Description of the Parameter
     *@return              The y value
     */
    public static int getY( Integer nodeInteger )
    {

        return implmnt.getY(nodeInteger);
    }


    /**
     *  Flatten the LatticeTree into an ArrayList to be used by the Generic
     *  Algorithms
     *
     *@param  flatLattice   The feature to be added to the Root attribute
     *@param  thisRootNode  The feature to be added to the Root attribute
     *@return               Description of the Return Value
     */
    public static ArrayList<LatticeNode> addRoot( ArrayList<LatticeNode> flatLattice, LatticeNode thisRootNode )
    {
        return implmnt.addRoot(flatLattice, thisRootNode);
    }


    /**
     *  Description of the Method
     *
     *@return    Description of the Return Value
     */
    public static int calcMaxDistance()
    {
        return implmnt.calcMaxDistance();
    }


    /**
     *  Store the maximum Number of nodes in a level
     *
     *@return    Description of the Return Value
     */
    public static int calcMaxNodesPerLevel()
    {

        return implmnt.calcMaxNodesPerLevel();
    }


    /**
     *  SLook for the level that the node was associated with. Decrease the
     *  count on this level. INcrease in the new level
     *
     *@param  node      Description of the Parameter
     *@param  newLevel  Description of the Parameter
     */
    public static void changeNodesPerLevel( LatticeNode node, Integer newLevel )
    {
        implmnt.changeNodesPerLevel(node, newLevel);
    }


    /**
     *  Store the number of levels
     *
     *@param  currentLevel  Description of the Parameter
     */
    public static void checkMaxLevel( int currentLevel )
    {
       implmnt.checkMaxLevel( currentLevel);
    }


    /**
     *  Function to take a higher level node and make a new LatticeTree based upon
     *  the Childs and the direct parents of these Child objects. The User will
     *  have read access to all nodes. But not have write access to Nodes that are
     *  not direct children. (e.g. the parents of a child)
     *
     *@param  keyNode                       Description of the Parameter
     *@return                               Description of the Return Value
     *@exception  NullLatticeNodeException  Description of the Exception
     */
    public static Object getChildTree(LatticeNode keyNode)
        throws NullLatticeNodeException, InvalidLatticeStructureException
    {

        return implmnt.getChildTree( keyNode );
    }

 /**
     *  Function to take a higher level node and make a new LatticeTree based upon
     *  the Childs and the direct parents of these Child objects. The User will
     *  have read access to all nodes. But not have write access to Nodes that are
     *  not direct children. (e.g. the parents of a child)
     *
     *@param  keyNode                       Description of the Parameter
     *@return                               Description of the Return Value
     *@exception  NullLatticeNodeException  Description of the Exception
     */
    public static Object getChildTreeNoParents(LatticeNode keyNode)
        throws NullLatticeNodeException, InvalidLatticeStructureException
    {

        return implmnt.getChildTreeNoParents( keyNode );
    }

    /**
     *  Flatten the LatticeTree into an ArrayList to be used by the Generic
     *  Algorithms
     *
     *@param  keyNode                               Description of the Parameter
     *@param  copyNode                              Description of the Parameter
     *@param  childTree                             Description of the Parameter
     *@return                                       Description of the Return
     *      Value
     *@exception  InvalidLatticeStructureException  Description of the Exception
     */
    public static Object copyAllChildren( LatticeNode keyNode, LatticeNode copyNode, LatticeTree childTree )
        throws InvalidLatticeStructureException
    {
        return implmnt.copyAllChildren( keyNode, copyNode, childTree );
    }


    /**
     *  Holding place function.
     *  For case where the use wishes to get a subset of the
     * Lattice Tree. WHich may be a composite of child tree and
     * other node types.
     *
     *@param  keyNode                       Description of the Parameter
     *@return                               Description of the Return Value
     *@exception  NullLatticeNodeException  Description of the Exception
     */
    public static Object getSubTree(LatticeTree originalTree , LatticeNode keyNode)
        throws NullLatticeNodeException, InvalidLatticeStructureException
    {
        /*
         *
         */
        return implmnt.getSubTree(originalTree, keyNode);
    }

/**
     *  Flatten the LatticeTree into an ArrayList to be used by the Generic
     *  Algorithms
     *
     *@param  keyNode                               Description of the Parameter
     *@param  copyNode                              Description of the Parameter
     *@param  childTree                             Description of the Parameter
     *@return                                       Description of the Return
     *      Value
     *@exception  InvalidLatticeStructureException  Description of the Exception
     */
    public Object copyOnlyChildren( LatticeNode keyNode, LatticeNode copyNode, LatticeTree childTree )
        throws InvalidLatticeStructureException
    {
	 return implmnt.copyOnlyChildren( keyNode, copyNode, childTree );

    }
    /**
     *  Flatten the LatticeTree into an ArrayList to be used by the Generic
     *  Algorithms
     *
     *@param  flatLattice  Description of the Parameter
     *@param  rootNode     Description of the Parameter
     *@param  level        Description of the Parameter
     *@return              Description of the Return Value
     */
    public static ArrayList<LatticeNode> flattenLattice( ArrayList<LatticeNode> flatLattice, LatticeNode rootNode, int level )
    {
        return implmnt.flattenLattice( flatLattice, rootNode, level) ;
    }


    /**
     *  Description of the Method
     *
     *@param  root  Description of the Parameter
     *@return       Description of the Return Value
     */
    public static int initialize( LatticeNode root )
    {

        return implmnt.initialize( root );
    }


    /**
     *  Description of the Method
     *
     *@param  filename            Description of the Parameter
     *@return                     Description of the Return Value
     *@exception  MraldException  Description of the Exception
     */
    public static LatticeTree recoverLatticeTree( String filename )
        throws MraldException, FileNotFoundException, IOException
    {
        return implmnt.recoverLatticeTree( filename );
    }


    /**
     *  Description of the Method
     */
    public static void reset()
    {
        implmnt.reset();
    }


    /**
     *  Serializes an LatticeTree to a file
     *
     *@param  filename         Path and name of the file to create/overwrite
     *@param  tree             The LatticeTree object to serialize
     *@exception  IOException  Description of the Exception
     */
    public static void serializeLatticeTree( LatticeTree tree, String filename )
        throws IOException
    {
        implmnt.serializeLatticeTree( tree,filename );
    }


    /**
     *@param  genesOnThisLevel  ArrayList of IntegerGene's representing the
     *      horizontal locations of the nodes
     *@return                   Description of the Return Value
     */
    public static ArrayList<IntegerGene> snap( ArrayList<IntegerGene> genesOnThisLevel )
    {
        return implmnt.snap( genesOnThisLevel);
    }


    /**
     *  Takes the x value of the Node, and 'Snaps to Grid' to neaten
     *
     *@param  values  Description of the Parameter
     *@return         Description of the Return Value
     */
    public static Gene[] snapToGrid( Gene[] values )
    {

        return implmnt.snapToGrid( values );
    }


    /**
     *  Description of the Method
     *
     *@param  genesOnThisLevel  Description of the Parameter
     *@return                   Description of the Return Value
     */
    public static ArrayList<IntegerGene> spaceNodes( ArrayList<IntegerGene> genesOnThisLevel )
    {

        return implmnt.spaceNodes(genesOnThisLevel);
    }


    /**
     *  Description of the Method
     *
     *@param  values  Description of the Parameter
     *@return         Description of the Return Value
     */
    public static Gene[] spaceOutLevels( Gene[] values )
    {

        return implmnt.spaceOutLevels( values );
    }

    /**
     *  Gets the body attribute of the BuildForm object
     *
     *@return                   The body value
     *@exception  SQLException  Description of the Exception	 try{
            */
    public static java.util.List sort(ArrayList groupList)
    {
       return implmnt.sort( groupList );
    }

  /**
     *  Gets the body attribute of the BuildForm object
     *
     *@return                   The body value
     *@exception  SQLException  Description of the Exception	 try{
            */
    public static int getScreenWidth()
    {
       return implmnt.getScreenWidth();
    }
}

